<?php

namespace Home\Service;

use Home\Common\FIdConst;

/**
 * 报损报溢Service
 *
 * @author 李静波
 */
class LOBillService extends PSIBaseService {
	private $LOG_CATEGORY = "报损报溢";

	/**
	 * 生成新的损溢单单号
	 *
	 * @return string
	 */
	private function genNewBillRef() {
		$pre = "LO";
		
		$mid = date("Ymd");
		
		$sql = "select ref from t_lo_bill where ref like '%s' order by ref desc limit 1";
		$data = M()->query($sql, $pre . $mid . "%");
		$sufLength = 3;
		$suf = str_pad("1", $sufLength, "0", STR_PAD_LEFT);
		if ($data) {
			$ref = $data[0]["ref"];
			$nextNumber = intval(substr($ref, strlen($pre . $mid))) + 1;
			$suf = str_pad($nextNumber, $sufLength, "0", STR_PAD_LEFT);
		}
		
		return $pre . $mid . $suf;
	}

	/**
	 * 获得某个损溢单的详情
	 */
	public function loBillInfo($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$id = $params["id"];
		
		$result = array();
		
		if ($id) {
			// 编辑
			$db = M();
			$sql = "select t.ref, t.bill_status, t.bizdt, t.biz_user_id, u.name as biz_user_name,
						w.id as warehouse_id, w.name as warehouse_name
					from t_lo_bill t, t_user u, t_warehouse w
					where t.id = '%s' and t.biz_user_id = u.id
					      and t.warehouse_id = w.id";
			$data = $db->query($sql, $id);
			if (! $data) {
				return $result;
			}
			
			$result["bizUserId"] = $data[0]["biz_user_id"];
			$result["bizUserName"] = $data[0]["biz_user_name"];
			$result["ref"] = $data[0]["ref"];
			$result["billStatus"] = $data[0]["bill_status"];
			$result["bizDT"] = date("Y-m-d", strtotime($data[0]["bizdt"]));
			$result["warehouseId"] = $data[0]["warehouse_id"];
			$result["warehouseName"] = $data[0]["warehouse_name"];
			
			$items = array();
			$sql = "select t.id, g.id as goods_id, g.code, g.name, g.spec, u.name as unit_name, 
						t.goods_count, t.qc_begin_dt, t.expiration, t.qc_end_dt, t.loss_or_over,
						t.note
				from t_lo_bill_detail t, t_goods g, t_goods_unit u
				where t.lobill_id = '%s' and t.goods_id = g.id and g.unit_id = u.id
				order by t.show_order ";
			
			$data = $db->query($sql, $id);
			foreach ( $data as $i => $v ) {
				$items[$i]["id"] = $v["id"];
				$items[$i]["goodsId"] = $v["goods_id"];
				$items[$i]["goodsCode"] = $v["code"];
				$items[$i]["goodsName"] = $v["name"];
				$items[$i]["goodsSpec"] = $v["spec"];
				$items[$i]["unitName"] = $v["unit_name"];
				$items[$i]["goodsCount"] = $v["goods_count"];
				
				$beginDT = $this->toYmdForQC($v["qc_begin_dt"]);
				if ($beginDT) {
					$items[$i]["qcBeginDT"] = $beginDT;
				}
				
				$expiration = $v["expiration"];
				if ($expiration > 0) {
					$items[$i]["expiration"] = $expiration;
				}
				
				$endDT = $this->toYmdForQC($v["qc_end_dt"]);
				if ($endDT) {
					$items[$i]["qcEndDT"] = $endDT;
				}
				
				$items[$i]["lossOrOver"] = $v["loss_or_over"] == 1 ? "损" : "溢";
				$items[$i]["note"] = $v["note"];
			}
			
			$result["items"] = $items;
		} else {
			// 新建
			$us = new UserService();
			$result["bizUserId"] = $us->getLoginUserId();
			$result["bizUserName"] = $us->getLoginUserName();
		}
		
		return $result;
	}

	/**
	 * 新增或编辑损溢单
	 */
	public function editLOBill($params) {
		if ($this->isNotOnline()) {
			return $this->notOnlineError();
		}
		
		$json = $params["jsonStr"];
		
		$bill = json_decode(html_entity_decode($json), true);
		if ($bill == null) {
			return $this->bad("传入的参数错误，不是正确的JSON格式");
		}
		
		$id = $bill["id"];
		$bizDT = $bill["bizDT"];
		$warehouseId = $bill["warehouseId"];
		$bizUserId = $bill["bizUserId"];
		$items = $bill["items"];
		
		$db = M();
		$db->startTrans();
		
		// 检查业务日期
		if (! $this->dateIsValid($bizDT)) {
			$db->rollback();
			return $this->bad("业务日期不正确");
		}
		
		$ws = new WarehouseService();
		if (! $ws->warehouseExists($warehouseId, $db)) {
			$db->rollback();
			return $this->bad("仓库不存在");
		}
		
		$us = new UserService();
		if (! $us->userExists($bizUserId, $db)) {
			$db->rollback();
			return $this->bad("业务员不存在");
		}
		
		$dataOrg = $us->getLoginUserDataOrg();
		$companyId = $us->getCompanyId();
		$userId = $us->getLoginUserId();
		
		$idGen = new IdGenService();
		
		$log = null;
		if ($id) {
			// 编辑
			$sql = "select ref, bill_status from t_lo_bill where id = '%s' ";
			$data = $db->query($sql, $id);
			if (! $data) {
				$db->rollback();
				return $this->bad("要编辑的损溢单不存在");
			}
			$ref = $data[0]["ref"];
			$billStatus = $data[0]["bill_status"];
			if ($billStatus > 0) {
				$db->rollback();
				return $this->bad("损溢单[单号 {$ref}]已经被审核，不能再编辑");
			}
			
			// 主表
			$sql = "update t_lo_bill
					set bizdt = '%s', biz_user_id = '%s', warehouse_id = '%s'
					where id = '%s' ";
			$rc = $db->execute($sql, $bizDT, $bizUserId, $warehouseId, $id);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			
			// 明细记录
			// 先清空原来的数据，再重新插入
			$sql = "delete from t_lo_bill_detail where lobill_id = '%s' ";
			$rc = $db->execute($sql, $id);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			
			foreach ( $items as $i => $v ) {
				$goodsId = $v["goodsId"];
				$goodsCount = $v["goodsCount"];
				$qcBeginDT = $v["qcBeginDT"];
				if (! $qcBeginDT) {
					$qcBeginDT = "1970-01-01";
				}
				
				$expiration = $v["expiration"];
				if (! $expiration) {
					$expiration = 0;
				}
				$qcEndDT = date("Y-m-d", strtotime($qcBeginDT . " +$expiration day"));
				
				$lossOrOver = $v["lossOrOver"] == "损" ? 1 : - 1;
				$note = $v["note"];
				
				if (! $goodsId) {
					continue;
				}
				
				// 检查商品是否存在
				$sql = "select id from t_goods where id = '%s' ";
				$data = $db->query($sql, $goodsId);
				if (! $data) {
					continue;
				}
				
				$sql = "insert into t_lo_bill_detail (id, date_created, goods_id, goods_count, show_order,
							lobill_id, data_org, company_id, qc_begin_dt, expiration, qc_end_dt,
							loss_or_over, note)
						values ('%s', now(), '%s', %d, %d,
							'%s', '%s', '%s', '%s', %d, '%s',
							%d, '%s')";
				$rc = $db->execute($sql, $idGen->newId($db), $goodsId, $goodsCount, $i, $id, 
						$dataOrg, $companyId, $qcBeginDT, $expiration, $qcEndDT, $lossOrOver, $note);
				if ($rc === false) {
					$db->rollback();
					return $this->sqlError(__LINE__);
				}
			}
			
			$log = "编辑损溢单，单号 {$ref}";
		} else {
			// 新建
			$ref = $this->genNewBillRef();
			
			// 主表
			$id = $idGen->newId($db);
			
			$sql = "insert into t_lo_bill (id, bill_status, ref, bizdt, biz_user_id,
						date_created, input_user_id, warehouse_id, data_org, company_id)
					values ('%s', 0, '%s', '%s', '%s', now(), '%s', '%s', '%s', '%s')";
			$rc = $db->execute($sql, $id, $ref, $bizDT, $bizUserId, $userId, $warehouseId, $dataOrg, 
					$companyId);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			
			// 明细记录
			foreach ( $items as $i => $v ) {
				$goodsId = $v["goodsId"];
				$goodsCount = $v["goodsCount"];
				$qcBeginDT = $v["qcBeginDT"];
				if (! $qcBeginDT) {
					$qcBeginDT = "1970-01-01";
				}
				
				$expiration = $v["expiration"];
				if (! $expiration) {
					$expiration = 0;
				}
				$qcEndDT = date("Y-m-d", strtotime($qcBeginDT . " +$expiration day"));
				
				$lossOrOver = $v["lossOrOver"] == "损" ? 1 : - 1;
				$note = $v["note"];
				
				if (! $goodsId) {
					continue;
				}
				
				// 检查商品是否存在
				$sql = "select id from t_goods where id = '%s' ";
				$data = $db->query($sql, $goodsId);
				if (! $data) {
					continue;
				}
				
				$sql = "insert into t_lo_bill_detail (id, date_created, goods_id, goods_count, show_order,
							lobill_id, data_org, company_id, qc_begin_dt, expiration, qc_end_dt, 
							loss_or_over, note)
						values ('%s', now(), '%s', %d, %d, 
							'%s', '%s', '%s', '%s', %d, '%s',
							%d, '%s')";
				$rc = $db->execute($sql, $idGen->newId($db), $goodsId, $goodsCount, $i, $id, 
						$dataOrg, $companyId, $qcBeginDT, $expiration, $qcEndDT, $lossOrOver, $note);
				if ($rc === false) {
					$db->rollback();
					return $this->sqlError(__LINE__);
				}
			}
			
			$log = "新建损溢单，单号 {$ref}";
		}
		
		// 记录业务日志
		if ($log) {
			$bs = new BizlogService();
			$bs->insertBizlog($log, $this->LOG_CATEGORY);
		}
		
		$db->commit();
		
		return $this->ok($id);
	}

	public function lobillList($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$start = $params["start"];
		$limit = $params["limit"];
		
		$billStatus = $params["billStatus"];
		$ref = $params["ref"];
		$fromDT = $params["fromDT"];
		$toDT = $params["toDT"];
		$warehouseId = $params["warehouseId"];
		
		$db = M();
		
		$sql = "
			select t.id, t.ref, t.bizdt, t.bill_status,
				w.name as warehouse_name,
				u.name as biz_user_name,
				u1.name as input_user_name,
				t.date_created, t.confirm_dt, t.confirm_user_id,
				t.icbill_ref
			from t_lo_bill t, t_warehouse w, t_user u, t_user u1
			where (t.warehouse_id = w.id)
			and (t.biz_user_id = u.id)
			and (t.input_user_id = u1.id) ";
		$queryParams = array();
		
		$ds = new DataOrgService();
		$rs = $ds->buildSQL(FIdConst::LOSS_OR_OVER_MANAGEMNET, "t");
		if ($rs) {
			$sql .= " and " . $rs[0];
			$queryParams = $rs[1];
		}
		
		if ($billStatus != - 1) {
			$sql .= " and (t.bill_status = %d) ";
			$queryParams[] = $billStatus;
		}
		if ($ref) {
			$sql .= " and (t.ref like '%s') ";
			$queryParams[] = "%{$ref}%";
		}
		if ($fromDT) {
			$sql .= " and (t.bizdt >= '%s') ";
			$queryParams[] = $fromDT;
		}
		if ($toDT) {
			$sql .= " and (t.bizdt <= '%s') ";
			$queryParams[] = $toDT;
		}
		if ($warehouseId) {
			$sql .= " and (t.warehouse_id = '%s') ";
			$queryParams[] = $warehouseId;
		}
		
		$sql .= " order by t.bizdt desc, t.ref desc
			limit %d , %d ";
		$queryParams[] = $start;
		$queryParams[] = $limit;
		$data = $db->query($sql, $queryParams);
		$result = array();
		foreach ( $data as $v ) {
			$item = array(
					"id" => $v["id"],
					"ref" => $v["ref"],
					"bizDate" => $this->toYMD($v["bizdt"]),
					"billStatus" => $v["bill_status"] == 0 ? "待审核" : "已审核",
					"warehouseName" => $v["warehouse_name"],
					"inputUserName" => $v["input_user_name"],
					"bizUserName" => $v["biz_user_name"],
					"dateCreated" => $v["date_created"]
			);
			
			$confirmUserId = $v["confirm_user_id"];
			if ($confirmUserId) {
				$item["confirmDT"] = $v["confirm_dt"];
				$item["icbillRef"] = $v["icbill_ref"];
				
				$sql = "select name from t_user where id = '%s' ";
				$d = $db->query($sql, $confirmUserId);
				if ($d) {
					$item["confirmUserName"] = $d[0]["name"];
				}
			}
			
			$result[] = $item;
		}
		
		$sql = "select count(*) as cnt
				from t_lo_bill t, t_warehouse w, t_user u, t_user u1
				where (t.warehouse_id = w.id)
				  and (t.biz_user_id = u.id)
				  and (t.input_user_id = u1.id) 
				";
		$queryParams = array();
		
		$ds = new DataOrgService();
		$rs = $ds->buildSQL(FIdConst::LOSS_OR_OVER_MANAGEMNET, "t");
		if ($rs) {
			$sql .= " and " . $rs[0];
			$queryParams = $rs[1];
		}
		
		if ($billStatus != - 1) {
			$sql .= " and (t.bill_status = %d) ";
			$queryParams[] = $billStatus;
		}
		if ($ref) {
			$sql .= " and (t.ref like '%s') ";
			$queryParams[] = "%{$ref}%";
		}
		if ($fromDT) {
			$sql .= " and (t.bizdt >= '%s') ";
			$queryParams[] = $fromDT;
		}
		if ($toDT) {
			$sql .= " and (t.bizdt <= '%s') ";
			$queryParams[] = $toDT;
		}
		if ($warehouseId) {
			$sql .= " and (t.warehouse_id = '%s') ";
			$queryParams[] = $warehouseId;
		}
		$data = $db->query($sql, $queryParams);
		$cnt = $data[0]["cnt"];
		
		return array(
				"dataList" => $result,
				"totalCount" => $cnt
		);
	}

	public function loBillDetailList($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$result = array();
		
		$id = $params["id"];
		
		$result = array();
		
		$db = M();
		$sql = "select t.id, g.code, g.name, g.spec, u.name as unit_name, t.goods_count, t.goods_money,
					t.qc_begin_dt, t.qc_end_dt, t.expiration, t.loss_or_over, t.note
				from t_lo_bill_detail t, t_goods g, t_goods_unit u
				where t.lobill_id = '%s' and t.goods_id = g.id and g.unit_id = u.id
				order by t.show_order ";
		
		$data = $db->query($sql, $id);
		foreach ( $data as $v ) {
			$item = array(
					"id" => $v["id"],
					"goodsCode" => $v["code"],
					"goodsName" => $v["name"],
					"goodsSpec" => $v["spec"],
					"unitName" => $v["unit_name"],
					"goodsCount" => $v["goods_count"],
					"lossOrOver" => $v["loss_or_over"] == 1 ? "损" : "溢",
					"note" => $v["note"]
			);
			
			$beginDT = $this->toYMD($v["qc_begin_dt"]);
			if ($beginDT && $beginDT != "1970-01-01") {
				$item["qcBeginDT"] = $beginDT;
			}
			
			$endDT = $this->toYMD($v["qc_end_dt"]);
			if ($endDT && $endDT != "1970-01-01") {
				$item["qcEndDT"] = $endDT;
			}
			
			$expiration = $v["expiration"];
			if ($expiration > 0) {
				$item["expiration"] = $expiration;
			}
			
			$result[] = $item;
		}
		
		return $result;
	}

	public function deleteLOBill($params) {
		if ($this->isNotOnline()) {
			return $this->notOnlineError();
		}
		
		$id = $params["id"];
		
		$db = M();
		
		$db->startTrans();
		
		$sql = "select ref, bill_status from t_lo_bill where id = '%s' ";
		$data = $db->query($sql, $id);
		if (! $data) {
			$db->rollback();
			return $this->bad("要删除的损溢单不存在");
		}
		
		$ref = $data[0]["ref"];
		$billStatus = $data[0]["bill_status"];
		if ($billStatus > 0) {
			$db->rollback();
			return $this->bad("单号为[{$ref}]的损溢单已经被审核，不能删除");
		}
		
		$sql = "delete from t_lo_bill_detail where lobill_id = '%s' ";
		$rc = $db->execute($sql, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		$sql = "delete from t_lo_bill where id = '%s' ";
		$rc = $db->execute($sql, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		$log = "删除损溢单，单号:{$ref}";
		$bs = new BizlogService();
		$bs->insertBizlog($log, $this->LOG_CATEGORY);
		
		$db->commit();
		
		return $this->ok();
	}

	/**
	 * 审核损溢单
	 */
	public function commitLOBill($params) {
		if ($this->isNotOnline()) {
			return $this->notOnlineError();
		}
		
		$id = $params["id"];
		
		$db = M();
		$db->startTrans();
		
		$sql = "select ref, bill_status from t_lo_bill where id = '%s' ";
		$data = $db->query($sql, $id);
		if (! $data) {
			$db->rollback();
			return $this->bad("要审核的损溢单不存在");
		}
		
		$ref = $data[0]["ref"];
		$billStatus = $data[0]["bill_status"];
		if ($billStatus > 0) {
			$db->rollback();
			return $this->bad("单号为 {$ref} 的损溢单已经审核，不能再次审核");
		}
		
		// 创建盘点单
		$ics = new ICBillService();
		$result = $ics->createICBillFromLOBill($id, $db);
		if ($result != null) {
			$db->rollback();
			return $result;
		}
		
		// 修改本单据的状态
		$us = new UserService();
		$userId = $us->getLoginUserId();
		
		$sql = "update t_lo_bill
				set bill_status = 1000, confirm_dt = now(),
					confirm_user_id = '%s'
				where id = '%s' ";
		$rc = $db->execute($sql, $userId, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		// 记录业务日志
		$log = "审核损溢单，单号：{$ref}";
		$bs = new BizlogService();
		$bs->insertBizlog($log, $this->LOG_CATEGORY);
		
		$db->commit();
		
		return $this->ok($id);
	}

	/**
	 * 取消审核损溢单
	 */
	public function cancelCommitLOBill($params) {
		if ($this->isNotOnline()) {
			return $this->notOnlineError();
		}
		
		$id = $params["id"];
		
		$db = M();
		
		$db->startTrans();
		
		$sql = "select ref, bill_status, icbill_id, icbill_ref 
				from t_lo_bill where id = '%s' ";
		$data = $db->query($sql, $id);
		if (! $data) {
			$db->rollback();
			return $this->bad("取消审核的损溢单不存在");
		}
		
		$ref = $data[0]["ref"];
		$billStatus = $data[0]["bill_status"];
		$icBillId = $data[0]["icbill_id"];
		$icBillRef = $data[0]["icbill_ref"];
		
		if ($billStatus == 0) {
			$db->rollback();
			return $this->bad("损溢单(单号：{$ref})还没有审核，不需要取消审核");
		}
		
		// 判断对应的盘点单是否已经提交，如果已经提交那么本损溢单就不能取消审核
		$sql = "select bill_status from t_ic_bill where id = '%s' ";
		$data = $db->query($sql, $icBillId);
		if ($data) {
			$billStatus = $data[0]["bill_status"];
			if ($billStatus > 0) {
				$db->rollback();
				$info = "本损溢单审核后生成的盘点单(单号：{$icBillRef})已经提交，所以本损溢单不能取消审核";
				return $this->bad($info);
			}
		}
		
		// 删除生成的盘点单数据
		$sql = "delete from t_ic_bill_detail where icbill_id = '%s' ";
		$rc = $db->execute($sql, $icBillId);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		$sql = "delete from t_ic_bill where id = '%s' ";
		$rc = $db->execute($sql, $icBillId);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		// 修改本损溢单的状态
		$sql = "update t_lo_bill
				set confirm_dt = null, confirm_user_id = null,
					icbill_id = null, icbill_ref = null,
					bill_status = 0
				where id = '%s' ";
		$rc = $db->execute($sql, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		// 记录业务日志
		$log = "取消审核损溢单，单号：{$ref}";
		$bs = new BizlogService();
		$bs->insertBizlog($log, $this->LOG_CATEGORY);
		
		$db->commit();
		
		return $this->ok($id);
	}
}